import org.jbox2d.collision.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BoundaryListener;
import org.jbox2d.dynamics.joints.MouseJoint;

import pulpcore.Input;
import pulpcore.Stage;
import pulpcore.animation.Timeline;
import pulpcore.sprite.ImageSprite;
import pulpfizz.physics.Actor;
import pulpfizz.physics.Material;
import pulpfizz.physics.NewWorld;
import pulpfizz.physics.contact.ContactData;
import pulpfizz.physics.contact.ContactEventListener;
import pulpfizz.pulp.CameraControlledScene;
import pulpfizz.pulp.body.PhysicsLayer;
import pulpfizz.pulp.ui.SmoothMouse;

public class OnePlayerScene extends CameraControlledScene implements ContactEventListener, BoundaryListener
{
	public static final int BULLET_GROUP = 0;
	public static final int PLAYER_GROUP = 1;
	public static final int PUCK_GROUP = 2;
	public static final int PUCK_SENSOR = 3;
	public static final int ARENA_SENSOR = 4;

	private SmoothMouse sm;
	private MouseJoint mj;
	private PhysicsLayer physics;

	Player player1;
	private Player player2;
	private Puck puck;
	private float size;

	@Override
	public void load()
	{
		super.load();

		add(new ImageSprite("background.png", 0, 0));

		camera.zoomTo(1.4f);
		camera.fastForward();
		camera.setRespondToInput(false);

		physics = new PhysicsLayer(30, 0, 0, 0, 0);
		physics.fitToStage();
		add(physics);

		createWorld();
	}

	public void createWorld()
	{
		NewWorld world = physics.getWorld();
		world.setGravity(new Vec2(0, 0));

		world.getContactEventDispatcher().registerGroupListener(PLAYER_GROUP, this);
		world.getContactEventDispatcher().registerGroupListener(ARENA_SENSOR, this);
		world.setBoundaryListener(this);

		Material m;
		Body b;

		m = Material.STONE();

//		physics.add(new Java2DBodySprite(BodyUtils.createBoundingBox(world, 1), physics));

		// Create a circle bounding box.
		float w = physics.getPhysicsWidth();
		float h = physics.getPhysicsHeight();

		System.out.println(physics.getWorld().getAABB());

		size = h * .33f;
		float THICKNESS = size / 10;
		float PLAYER_SIZE = size / 25f;

		Arena a = new Arena(physics, size, THICKNESS,false);

		player1 = new Player(physics, size - THICKNESS - PLAYER_SIZE * 1.5f, PLAYER_SIZE, +.4f);
		player1.setControls(Input.KEY_LEFT, Input.KEY_RIGHT, Input.KEY_DOWN, Input.KEY_SPACE);
		player1.setName("Player 1");

		player2 = new Player(physics, size - THICKNESS - PLAYER_SIZE * 1.5f, PLAYER_SIZE, (float) Math.PI - .4f);
		player2.setControls(Input.KEY_Q, Input.KEY_Z, Input.KEY_A, Input.KEY_LEFT_CONTROL);
		player2.setName("Player 1");

		launchPuck();
	}

	long time = 0;

	@Override
	public void update(int elapsedTime)
	{
		super.update(elapsedTime);
		this.time += elapsedTime;
		if (puck != null)
			puck.collideWithStuff.update(elapsedTime);
			
		//		System.out.println("Puck: "+puck.body.getPosition());
	}

	boolean fromTop = false;

	public void launchPuck()
	{
//		puck = new Puck(physics,size);
		puck.collideWithStuff.set(false);
		if (fromTop)
		{
			puck.body.setXForm(new Vec2(0, physics.getPhysicsHeight()), 0);
			puck.body.setLinearVelocity(new Vec2(0, -3));
			puck.body.setAngularVelocity(-5f);
		} else
		{
			puck.body.setXForm(new Vec2(0, -physics.getPhysicsHeight()*.3f), 0);
			puck.body.setLinearVelocity(new Vec2(0, 3));
			puck.body.setAngularVelocity(5f);
		}
		
		Timeline t = new Timeline();
		addTimeline(t);
		t.at(500).set(puck.collideWithStuff, true);
		t.play();
	}

	public void trigger(ContactData c)
	{
		if (c.state == ContactData.PERSIST)
			return;

		Body b1 = c.shape1.getBody();
		Body b2 = c.shape2.getBody();

		Actor a1 = (Actor) b1.getUserData();
		Actor a2 = (Actor) b2.getUserData();

		Actor[] actors = new Actor[] { a1, a2 };
		Shape[] shapes = new Shape[] { c.shape1, c.shape2 };
		Body[] bodies = new Body[] { b1, b2 };
		for (int i = 0; i <= 1; i++)
		{
			for (int j = 0; j <= 1; j++)
			{
				if (i == j)
					continue;

				if (c.state == ContactData.ADD)
				{
					if (actors[i].isInGroup(PLAYER_GROUP) && actors[j].isInGroup(BULLET_GROUP))
					{
						// If we get here, then Player (actors[i]) has collided with Bullet (actors[j])
						Player p = (Player) actors[i];
						Bullet b = (Bullet) actors[j];
						p.grabBullet(b);
					} else if (actors[i].isInGroup(PUCK_GROUP) && actors[j].isInGroup(ARENA_SENSOR))
					{
						Puck p = (Puck) actors[i];
						Arena a = (Arena) actors[j];
						if (shapes[i] == p.sensor)
						{
							if (bodies[j] == a.player1Sensor && shapes[j] != a.player1Shield)
								playerScore(player1, p);
							else if (bodies[j] == a.player2Sensor && shapes[j] != a.player2Shield)
								playerScore(player2, p);
						}
					}
				}

				if (actors[i].isInGroup(PLAYER_GROUP) && actors[j].isInGroup(ARENA_SENSOR))
				{
					Player p = (Player) actors[i];
					Arena a = (Arena) actors[j];
					if (p == player1 && shapes[j] == a.player1Shield)
					{
						if (c.state == ContactData.ADD)
							player1.setDisabled(true);
						else
							player1.setDisabled(false);
					} else if (p == player2 && shapes[j] == a.player2Shield)
					{
						if (c.state == ContactData.ADD)
							player2.setDisabled(true);
						else
							player2.setDisabled(false);
					}
				}
			}
		}
	}

	void playerScore(Player player, Puck puck)
	{
		System.out.println(player.getName() + "  " + puck.getName());
	}

	public void violation(Body body)
	{
		Actor a = (Actor) body.getUserData();
		if (a != null)
		{
			if (a.isInGroup(BULLET_GROUP))
			{
				Bullet b = (Bullet) a;
				physics.remove(b.sprite);
				Player p = player1;
				if (b.parent == player1)
					p = player2;

				p.ammo += b.size;
			}
		}
	}
}
